﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace HCMUS_SearchService_Group2
{
    /////////////////////////////////////////////////
    /// \brief Lớp static hỗ trợ search.
    /// \author Trần Minh Nhật -   0912322.
    /// \details <h3>Cung cấp các phương thức giúp việc Search trở nên dễ dàng hơn</h3>
    ////////////////////////////////////////////////
    public class DefaultSearchEngine
    {
        private List<SearchResultObject> listSearchCandidate = new List<SearchResultObject>();

        public List<SearchResultObject> ListSearchCandidate
        {
            get 
            { return this.listSearchCandidate; }
            set { this.listSearchCandidate = value; }
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm
        /// \param[in] string strInput.
        /// \param[in] int maDichVu
        /// \param[out] Không 
        /// \returns List<ContentDataDTO>.
        /// \details <h3>Trả về danh sách các dữ liệu gốc.</h3>
        /////////////////////////////////////////////////
        public List<ContentDataDTO> Search(string strInput, int maDichVu)
        {
            /// - Bước 1: Khởi tạo danh sách chứa các từ khóa tìm kiếm
            List<DataDTO> lstResult = new List<DataDTO>();

            if (null != this.ListSearchCandidate)
            {
                this.ListSearchCandidate.Clear();
            }
            else
            {
                this.ListSearchCandidate = new List<SearchResultObject>();
            }

            if (null != strInput)
            {
                /// \see TranslateHelper.FormatInputString(string);
                strInput = TranslateHelper.FormatInputString(strInput);

                /// - Bước 2: Kiểm tra người dùng có nhập input không
                if (strInput.Length > 0)
                {
                    /// \see SearchHelper.CheckExistNumber(string);
                    bool isExistNumber = SearchHelper.CheckExistNumber(strInput);
                    if (isExistNumber)
                    {
                        /// - Bước 3: Tìm kiếm các dịch vụ có địa chỉ chứa chuỗi input nếu chuỗi input chứa số
                        /// \see SearchHelper.SearchWithAdress(string);
                        List<DataDTO> lstDuLieuDTO = SearchHelper.SearchWithAdress(strInput);

                        /// - Bước 4: Xóa các mã địa chỉ trùng nhau 
                        /// \see SearchHelper.RemoveDuplicate(List<DataDTO>)
                        lstDuLieuDTO = SearchHelper.RemoveDuplicate(lstDuLieuDTO);

                        int nDuLieuDTO = lstDuLieuDTO.Count;
                        if (nDuLieuDTO > 0)
                        {
                            string strTemp = string.Empty;
                            for (int i = 0; i < nDuLieuDTO; i++)
                            {
                                if (lstDuLieuDTO[i].SoNha.Length == 0)
                                {
                                    continue;
                                }
                                /// - Bước 5: Xóa chuỗi số đã tìm kiếm trong các đối tượng dùng để tìm kiếm 
                                strTemp = strInput.Replace(lstDuLieuDTO[i].SoNha,string.Empty);                        
                                strTemp = strTemp.Trim();

                                /// - Bước 6: Tìm kiếm theo dịch vụ nếu có thể
                                if (strTemp.Length > 0)
                                {
                                    /// \see SearchTuKhoaDichVu(string , string, int)
                                    this.SearchTuKhoaDichVu(strTemp, lstDuLieuDTO[i].SoNha, maDichVu);
                                }
                                else
                                {
                                    SearchResultObject sr = new SearchResultObject() { Location = lstDuLieuDTO[i].SoNha };
                                    if (0 != maDichVu)
                                    {
                                        sr.ServiceID = maDichVu;
                                    }

                                    this.ListSearchCandidate.Add(sr);
                                }
                            }
                        }

                        /// \see SearchTuKhoaDichVu(string , string, int)
                        this.SearchTuKhoaDichVu(strInput, string.Empty, maDichVu);
                    }
                    else
                    {
                        /// \see SearchTuKhoaDichVu(string , string, int);
                        this.SearchTuKhoaDichVu(strInput, string.Empty, maDichVu);
                    }

                    /// - Bước 7: Tìm các dữ liệu có thể người dùng muốn tìm dựa vào kết quả từ việc phân tích các từ khóa
                    List<DataDTO> lstTemp = null;
                    for (int i = 0; i < this.ListSearchCandidate.Count; i++)
                    {
                        /// \see SearchHelper.SearchData(SearchResultObject);
                        lstTemp = SearchHelper.SearchData(this.ListSearchCandidate[i]);
                        lstResult.AddRange(lstTemp);
                    }
                }
                else
                {
                    if (0 != maDichVu)
                    {
                        /// \see SearchTuKhoaDichVu(string , string, int);
                        this.SearchTuKhoaDichVu(strInput, string.Empty, maDichVu);
                        List<DataDTO> lstTemp = null;
                        for (int i = 0; i < this.ListSearchCandidate.Count; i++)
                        {
                            /// \see SearchHelper.SearchData(SearchResultObject);
                            lstTemp = SearchHelper.SearchData(this.ListSearchCandidate[i]);
                            lstResult.AddRange(lstTemp);
                        }
                    }
                }
            }

            /// - Bước 8: Chuyển các mã đó ra dữ liệu cụ thể
            /// \see SearchHelper.RemoveDuplicateResult(List<DataDTO>);
            lstResult = SearchHelper.RemoveDuplicateResult(lstResult);
            List<ContentDataDTO> listContent = new List<ContentDataDTO>();
            for (int i = 0; i < lstResult.Count; i++)
            {
                /// \see SearchHelper.SearchDataByID(ContentDataDTO);
                ContentDataDTO temp = SearchHelper.SearchDataByID(lstResult[i], i);
                listContent.Add(temp);
            }

            DataConnectionHelper.ListResult.Clear();
            DataConnectionHelper.ListResult = listContent;
            return listContent;
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm theo Dịch Vụ
        /// \param[in] string strInput.
        /// \param[in] string soNha
        /// \param[in] int maDichVu
        /// \param[out] Không 
        /// \returns Không.
        /// \details <h3>Thêm vào ListSearchCandidate hoặc Search Theo Tỉnh Thành nếu có thể</h3>
        /////////////////////////////////////////////////
        private void SearchTuKhoaDichVu(string strInput, string soNha, int maDichVu)
        {
            /// - Bước 1: Kiểm tra có phải tìm tất cả dịch vụ không
            if (0 == maDichVu)
            {
                /// - Bước 2: Tìm kiếm các mã dịch vụ thích hợp theo từ khóa dịch vụ
                /// \see SearchHelper.SearchService(string);
                List<ServiceKeyDTO> lstTuKhoaDichVuDTO = SearchHelper.SearchService(strInput);
                
                /// \see SearchHelper.RemoveDuplicateServiceKey(List<ServiceKeyDTO);
                lstTuKhoaDichVuDTO = SearchHelper.RemoveDuplicateServiceKey(lstTuKhoaDichVuDTO);
                int nTuKhoaDichVuDTO = lstTuKhoaDichVuDTO.Count;
                if (nTuKhoaDichVuDTO > 0)
                {
                    string strTemp = string.Empty;
                    for (int i = 0; i < nTuKhoaDichVuDTO; i++)
                    {
                        if (lstTuKhoaDichVuDTO[i].ServiceKeyWord.Length == 0)
                        {
                            continue;
                        }
                        strTemp = strInput.Replace(lstTuKhoaDichVuDTO[i].ServiceKeyWord, string.Empty);                        
                        strTemp = strTemp.Trim();
                        if (strTemp.Length > 0)
                        {
                            /// \see SearchTuKhoaTinhThanh(string,int,int);
                            this.SearchTuKhoaTinhThanh(strTemp, soNha, lstTuKhoaDichVuDTO[i].ServiceID);
                        }
                        else
                        {
                            SearchResultObject sr = new SearchResultObject() { Location = soNha, ServiceID = lstTuKhoaDichVuDTO[i].ServiceID };
                            this.ListSearchCandidate.Add(sr);
                        }
                    }
                }
                
                /// \see SearchTuKhoaTinhThanh(string,int,int);
                this.SearchTuKhoaTinhThanh(strInput, soNha, DataConnectionHelper._defaultNumber);
            }
            else
            {
                if (0 == strInput.Length)
                {
                    SearchResultObject sr = new SearchResultObject() { Location = soNha, ServiceID = maDichVu };
                    this.ListSearchCandidate.Add(sr);
                }
                else
                {
                    /// \see SearchTuKhoaTinhThanh(string,int,int);
                    this.SearchTuKhoaTinhThanh(strInput, soNha, maDichVu);
                }                   
            }
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm theo Tỉnh Thành
        /// \param[in] string strInput.
        /// \param[in] string address
        /// \param[in] int serviceID
        /// \param[out] Không 
        /// \returns Không.
        /// \details <h3>Thêm vào ListSearchCandidate hoặc Search theo Quận/Huyện nếu có thể</h3>
        /////////////////////////////////////////////////
        private void SearchTuKhoaTinhThanh(string strInput, string address, int serviceID)
        {
            /// - Bước 1: Tìm kiếm các mã tỉnh thành thích hợp theo từ khóa tỉnh thành
            /// \see  SearchHelper.SearchCity(string);
            List<CityKeyDTO> lstTuKhoaTinhThanhDTO = SearchHelper.SearchCity(strInput);
            
            /// \see SearchHelper.RemoveDuplicateCityKey(List<CityKeyDTO>);
            lstTuKhoaTinhThanhDTO = SearchHelper.RemoveDuplicateCityKey(lstTuKhoaTinhThanhDTO);
            int nTuKhoaTinhThanhDTO = lstTuKhoaTinhThanhDTO.Count;
            if (nTuKhoaTinhThanhDTO > 0)
            {
                string strTemp = string.Empty;
                for (int i = 0; i < lstTuKhoaTinhThanhDTO.Count; i++)
                {
                    if (lstTuKhoaTinhThanhDTO[i].CityKeyWord.Length == 0)
                    {
                        continue;
                    }
                    strTemp = strInput.Replace(lstTuKhoaTinhThanhDTO[i].CityKeyWord, string.Empty);                        
                    strTemp = strTemp.Trim();
                    if (strTemp.Length > 0)
                    {
                        /// \see SearchTuKhoaQuanHuyen(string,string, int , int )
                        this.SearchTuKhoaQuanHuyen(strTemp, address, serviceID, lstTuKhoaTinhThanhDTO[i].CityID);
                    }
                    else
                    {
                        SearchResultObject sr = new SearchResultObject() { Location = address, ServiceID = serviceID, CityID = lstTuKhoaTinhThanhDTO[i].CityID };
                        this.ListSearchCandidate.Add(sr);
                    }
                }
            }

            /// \see SearchTuKhoaQuanHuyen
            this.SearchTuKhoaQuanHuyen(strInput, address, serviceID, DataConnectionHelper._defaultNumber);
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm theo Quận Huyện
        /// \param[in] string strInput.
        /// \param[in] string address
        /// \param[in] int serviceID
        /// \param[in] int cityID
        /// \param[out] Không 
        /// \returns Không.
        /// \details <h3>Thêm vào ListSearchCandidate hoặc Search theo Phường nếu có thể</h3>
        /////////////////////////////////////////////////
        private void SearchTuKhoaQuanHuyen(string strInput, string address, int serviceID, int cityID)
        {
            /// - Bước 1: Tìm kiếm các mã quận/huyện thích hợp theo từ khóa quận huyện
            /// \see  SearchHelper.SearchDistrict(string);
            List<DistrictKeyDTO> lstTuKhoaQuanHuyenDTO = SearchHelper.SearchDistrict(strInput);
            
            /// \see SearchHelper.RemoveDuplicateDistrictKey(List<DistrictKeyDTO>);
            lstTuKhoaQuanHuyenDTO = SearchHelper.RemoveDuplicateDistrictKey(lstTuKhoaQuanHuyenDTO);
            int nTuKhoaQuanHuyenDTO = lstTuKhoaQuanHuyenDTO.Count;
            if (nTuKhoaQuanHuyenDTO > 0)
            {
                string strTemp = string.Empty;
                for (int i = 0; i < lstTuKhoaQuanHuyenDTO.Count; i++)
                {
                    if (lstTuKhoaQuanHuyenDTO[i].DistrictKeyWord.Length == 0)
                    {
                        continue;
                    }
                    strTemp = strInput.Replace(lstTuKhoaQuanHuyenDTO[i].DistrictKeyWord, string.Empty);                        
                    strTemp = strTemp.Trim();
                    if (strTemp.Length > 0)
                    {
                        /// \see  SearchTuKhoaPhuong(string , string , int , int , int );
                        this.SearchTuKhoaPhuong(strTemp, address, serviceID, cityID, lstTuKhoaQuanHuyenDTO[i].DistrictID);
                    }
                    else
                    {
                        SearchResultObject sr = new SearchResultObject() { Location = address, ServiceID = serviceID, CityID = cityID, DistrictID = lstTuKhoaQuanHuyenDTO[i].DistrictID };
                        this.ListSearchCandidate.Add(sr);
                    }
                }
            }

            /// \see  SearchTuKhoaPhuong(string , string , int , int , int );
            this.SearchTuKhoaPhuong(strInput, address, serviceID, cityID, DataConnectionHelper._defaultNumber);
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm theo Phường
        /// \param[in] string strInput.
        /// \param[in] string address
        /// \param[in] int serviceID
        /// \param[in] int cityID
        /// \param[in] int districtID
        /// \param[out] Không 
        /// \returns Không.
        /// \details <h3>Thêm vào ListSearchCandidate hoặc Search theo Đường nếu có thể</h3>
        /////////////////////////////////////////////////
        private void SearchTuKhoaPhuong(string strInput, string address, int serviceID, int cityID, int districtID)
        {
            /// - Bước 1: Tìm kiếm các mã phường thích hợp theo từ khóa phường
            /// \see  SearchHelper.SearchWard(string);
            List<WardKeyDTO> lstTuKhoaPhuongDTO = SearchHelper.SearchWard(strInput);
            
            /// \see SearchHelper.RemoveDuplicateWardKey(List<WardKeyDTO>);
            lstTuKhoaPhuongDTO = SearchHelper.RemoveDuplicateWardKey(lstTuKhoaPhuongDTO);
            int nTuKhoaPhuongDTO = lstTuKhoaPhuongDTO.Count;
            if (nTuKhoaPhuongDTO > 0)
            {
                string strTemp = string.Empty;
                for (int i = 0; i < lstTuKhoaPhuongDTO.Count; i++)
                {
                    if(lstTuKhoaPhuongDTO[i].WardKeyWord.Length==0)
                    {
                        continue;
                    }
                    strTemp = strInput.Replace(lstTuKhoaPhuongDTO[i].WardKeyWord, string.Empty);                                  
                    strTemp = strTemp.Trim();
                    if (strTemp.Length > 0)
                    {
                        /// \see  SearchTuKhoaDuong(string , string , int , int , int , int );
                        this.SearchTuKhoaDuong(strTemp, address, serviceID, cityID, districtID, lstTuKhoaPhuongDTO[i].WardID);
                    }
                    else
                    {
                        SearchResultObject sr = new SearchResultObject() { Location = address, ServiceID = serviceID, CityID = cityID, DistrictID = districtID, WardID = lstTuKhoaPhuongDTO[i].WardID };
                        this.ListSearchCandidate.Add(sr);
                    }
                }
            }

            /// \see  SearchTuKhoaDuong(string , string , int , int , int , int );
            this.SearchTuKhoaDuong(strInput, address, serviceID, cityID, districtID, DataConnectionHelper._defaultNumber);
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm theo Phường
        /// \param[in] string strInput.
        /// \param[in] string address
        /// \param[in] int serviceID
        /// \param[in] int cityID
        /// \param[in] int districtID
        /// \param[in] int wardID
        /// \param[out] Không 
        /// \returns Không.
        /// \details <h3>Thêm vào ListSearchCandidate hoặc Search theo Địa Điểm nếu có thể</h3>
        /////////////////////////////////////////////////
        private void SearchTuKhoaDuong(string strInput, string address, int serviceID, int cityID, int districtID, int wardID)
        {
            /// - Bước 1: Tìm kiếm các mã đường thích hợp theo từ khóa đường
            /// \see  SearchHelper.SearchStreet(string);
            List<StreetKeyDTO> lstTuKhoaDuongDTO = SearchHelper.SearchStreet(strInput);
            
            /// \see SearchHelper.RemoveDuplicateStreetKey(List<StreetKeyDTO>);
            lstTuKhoaDuongDTO = SearchHelper.RemoveDuplicateStreetKey(lstTuKhoaDuongDTO);
            int nTuKhoaDuongDTO = lstTuKhoaDuongDTO.Count;
            if (nTuKhoaDuongDTO > 0)
            {
                string strTemp = string.Empty;
                for (int i = 0; i < lstTuKhoaDuongDTO.Count; i++)
                {
                    if (lstTuKhoaDuongDTO[i].StreetKeyWord.Length == 0)
                    {
                        continue;
                    }
                    strTemp = strInput.Replace(lstTuKhoaDuongDTO[i].StreetKeyWord, string.Empty);                 
                    strTemp = strTemp.Trim();
                    if (strTemp.Length > 0)
                    {
                        /// \see  SearchTuKhoaDiaDiem(string , string , int , int , int , int , int);
                        this.SearchTuKhoaDiaDiem(strTemp, address, serviceID, cityID, districtID, wardID, lstTuKhoaDuongDTO[i].StreetID);
                    }
                    else
                    {
                        SearchResultObject sr = new SearchResultObject() { Location = address, ServiceID = serviceID, CityID = cityID, DistrictID = districtID, WardID = wardID, StreetID = lstTuKhoaDuongDTO[i].StreetID };
                        this.ListSearchCandidate.Add(sr);
                    }
                }
            }

            /// \see  SearchTuKhoaDiaDiem(string , string , int , int , int , int , int);
            this.SearchTuKhoaDiaDiem(strInput, address, serviceID, cityID, districtID, wardID, DataConnectionHelper._defaultNumber);
        }

        /////////////////////////////////////////////////
        /// \brief Hàm tìm kiếm theo Phường
        /// \param[in] string strInput.
        /// \param[in] string address
        /// \param[in] int serviceID
        /// \param[in] int cityID
        /// \param[in] int districtID
        /// \param[in] int wardID
        /// \param[in] int streetID
        /// \param[out] Không 
        /// \returns Không.
        /// \details <h3>Thêm vào ListSearchCandidate.</h3>
        /////////////////////////////////////////////////
        private void SearchTuKhoaDiaDiem(string strInput, string location, int serviceID, int cityID, int districtID, int wardID, int streetID)
        {
            /// - Bước 1: Tìm kiếm các mã địa điểm thích hợp theo từ khóa địa điểm
            /// \see  SearchHelper.SearchLocation(string);
            List<LocationKeyDTO> lstTuKhoaDiaDiemDTO = SearchHelper.SearchLocation(strInput);
            
            /// \see SearchHelper.RemoveDuplicateLocationKey(List<LocationKeyDTO>);
            //lstTuKhoaDiaDiemDTO = SearchHelper.RemoveDuplicateLocationKey(lstTuKhoaDiaDiemDTO);
            int nTuKhoaDiaDiemDTO = lstTuKhoaDiaDiemDTO.Count;
            if (nTuKhoaDiaDiemDTO > 0)
            {
                string strTemp = string.Empty;
                for (int i = 0; i < lstTuKhoaDiaDiemDTO.Count; i++)
                {
                   // if (0 != TranslateHelper.FormatInputString(lstTuKhoaDiaDiemDTO[i].LocationKeyWord).Length)
                    if (lstTuKhoaDiaDiemDTO[i].LocationKeyWord.Length == 0)
                    {
                        continue;
                    }
                    strTemp = strInput.Replace(lstTuKhoaDiaDiemDTO[i].LocationKeyWord, string.Empty);                 
                    strTemp = strTemp.Trim();
                    if (0 == strTemp.Length)
                    {
                        SearchResultObject sr = new SearchResultObject() { Location = location, ServiceID = serviceID, CityID = cityID, DistrictID = districtID, WardID = wardID, StreetID = streetID, LocationID = lstTuKhoaDiaDiemDTO[i].LocationID };
                        this.ListSearchCandidate.Add(sr);                                         
                    }                                        
                }
            }            
        }

        /////////////////////////////////////////////////
        /// \brief Lấy Menu tương ứng.
        /// \param[in] ContentDataDTO data.
        /// \returns List<ServiceDetailDTO> .
        /// \details <h3>Lấy ra bảng Menu tương ứng với Dịch vụ cần tra cứu</h3>
        /////////////////////////////////////////////////
        public static List<ServiceDetailDTO> GetMenu(ContentDataDTO data)
        {
            return SearchHelper.GetMenu(data.MaDuLieu);
        }
    }
}
